package com.newfiber.business.controller.websocket;

import static cn.hutool.core.date.DatePattern.PURE_DATETIME_PATTERN;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson2.JSONObject;
import com.newfiber.business.domain.PatrolTask;
import com.newfiber.business.domain.request.patrolPath.PatrolPathSaveRequest;
import com.newfiber.business.enums.EPatrolRedisKey;
import com.newfiber.business.enums.EPatrolTaskStatus;
import com.newfiber.business.service.IPatrolTaskService;
import com.newfiber.common.redis.service.RedisService;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

/**
 * @author : X.K
 * @since : 2023/3/6 下午2:15
 */
@Slf4j
public class PatrolPathWebNotifySocket extends TextWebSocketHandler{

	private final List<WebSocketSession> webSocketSessionList = new ArrayList<>();

	@Resource
	private RedisService redisService;

	@Resource
	private IPatrolTaskService patrolTaskService;

	public void notifyPatrolPath(PatrolPathSaveRequest request){
		if(CollectionUtils.isNotEmpty(webSocketSessionList)){
			for(WebSocketSession webSocketSession : webSocketSessionList){
				try {
					if(webSocketSession.isOpen()){
						webSocketSession.sendMessage(new TextMessage(JSONObject.toJSONString(request)));
					}
				}catch (Exception e){
					log.error("发送巡查路径失败");
					e.printStackTrace();
				}
			}
		}
	}

	// TODO 测试造数据
	List<List<String>> patrolPathPool = new ArrayList<>();
	Map<Long, PoolIndex> poolIndexMap = new HashMap<>();

	{
//		patrolPathPool.add(Arrays.asList("114.39854660411555 30.482099648381038,114.39824822901357 30.482107150580052,114.3979651673985 30.482120675890354,114.39781122385128 30.48214962954071,114.39780327748623 30.482159025581222,114.3977449980312 30.48213697767745,114.39773822516088 30.481922818941367,114.39767691469473 30.481758728293503,114.39762329807778 30.481528099354968,114.39755491807261 30.481496234821027,114.39747302570049 30.481316639097184,114.39746671089667 30.48110918081967,114.39747340966218 30.48093168606247,114.39743328864719 30.480740153914546,114.39740698971073 30.48056569366831,114.39741241046748 30.480521919807977,114.39735486586365 30.480234536135573,114.39745537529788 30.480161555569275,114.39747863117904 30.480143247412073,114.39747854241165 30.47988623999544,114.39742412257903 30.47955181936501,114.39742727319177 30.47937093716357,114.39737781938956 30.479163120050163,114.39732072984904 30.478850738681757,114.39734105934691 30.47860513150429,114.39730144438181 30.47852006088943,114.3972527464163 30.478268798336394,114.39724604677411 30.47812535755401,114.39722168447699 30.477810374968,114.39722531738705 30.477697075496422,114.39720213733975 30.477577711637228,114.39711313560541 30.476874164203863,114.39709063008596 30.47669002344106,114.3970716453826 30.47657680070899,114.39702477508156 30.476319728483155,114.39701749629826 30.476130586038558,114.3970354042956 30.476004879850276,114.39698782149364 30.475895071296023,114.39683234402519 30.475915910286712,114.39680696073093 30.476102762058268,114.39689368385321 30.47623939489402,114.39689672035527 30.476372639775327,114.39695900787392 30.476605327668107,114.39692572014097 30.476744242767847,114.3970014781452 30.476938523191485,114.39701764378403 30.47716560208149,114.3970297222072 30.477403073886027,114.39702179821883 30.477609023342076,114.39698938614102 30.4777956220282,114.39704952085316 30.47789734913181,114.39702075084809 30.477953712382625,114.39708328488652 30.478340977286983,114.39718305303427 30.478583705493435,114.39723389289618 30.478793460650714,114.39720424038609 30.478936351380682,114.39722685476531 30.479130272453432,114.39734908943618 30.47918077318792,114.39750882177862 30.479148390898455,114.39760509125628 30.47913327096127".split(",")));
		patrolPathPool.add(Arrays.asList("114.3973733 30.47918173,114.3974946 30.47914873,114.3976055 30.47913368,114.3977823 30.47909465,114.3978897 30.47909165,114.3980838 30.47909165,114.3982675 30.47905261,114.3984615 30.47904063,114.3986175 30.47901358,114.3987422 30.47899857,114.3987353 30.47892352,114.3987041 30.47880645,114.3986417 30.47869841,114.3985724 30.47859638,114.3984789 30.47847336,114.3984026 30.47837135,114.3982953 30.47828136,114.3982295 30.47819137,114.3981464 30.47805941,114.3980913 30.47794846,114.3980529 30.47784652,114.3980218 30.47774759,114.3979941 30.47759472,114.3979803 30.47748678,114.3979561 30.47735487,114.3979423 30.47724696,114.3979077 30.47719301,114.3977415 30.47726495,114.3976134 30.47733389,114.3974679 30.47737286,114.3972602 30.47741183,114.3971843 30.47741782,114.3971873 30.47760371,114.3971976 30.47775365,114.3972148 30.47784963,114.3972286 30.47801163,114.3972354 30.47811957,114.3972492 30.47823657,114.3972629 30.47836258,114.3972802 30.47847663,114.3973043 30.47860565,114.3973146 30.47869569,114.3973215 30.47881877,114.3973563 30.47893586,114.3973563 30.47901393,114.3973628 30.47910702,114.3973697 30.47917609,114.3973733 30.47918173".split(",")));
		patrolPathPool.add(Arrays.asList("114.3976393 30.48086664,114.3977644 30.48086179,114.3978652 30.48086017,114.3980836 30.48084561,114.3981826 30.48084561,114.3982908 30.48083591,114.3984532 30.48081327,114.3986212 30.48079386,114.3987369 30.48077769,114.3988134 30.48075505,114.3988712 30.48071139,114.3988824 30.48063863,114.3989084 30.48055942,114.3989755 30.48046407,114.3990407 30.48039297,114.3990649 30.48035419,114.3990071 30.48028634,114.3989584 30.48019753,114.3989155 30.48012483,114.3988818 30.48006185,114.3988277 30.47992393,114.3988064 30.47985035,114.3987792 30.47977813,114.3987714 30.47972561,114.3987547 30.47966523,114.3987561 30.47959829,114.3987561 30.47953532,114.3987545 30.47946971,114.3987515 30.47940411,114.3987529 30.47933328,114.3987652 30.47928469,114.3987619 30.47920727,114.3987482 30.47910494,114.3987406 30.47905116,114.3987391 30.47901313,114.3986618 30.47901575,114.3985422 30.47902756,114.3984543 30.47903805,114.3983256 30.47904985,114.3981454 30.47907477,114.3980242 30.47908002,114.3978909 30.47909838,114.3978076 30.47910625,114.3977228 30.47911544,114.3976243 30.47912462,114.3975152 30.47914167,114.3974441 30.47916398,114.3973743 30.47918497,114.3973878 30.47930832,114.3973938 30.47937526,114.3974043 30.47943565,114.3974254 30.47959183,114.3974374 30.47966796,114.3974434 30.47973364,114.3974584 30.47982683,114.3974674 30.47990301,114.3974764 30.47997921,114.3974933 30.48003702,114.3974945 30.48010667,114.3975201 30.48025119,114.3975185 30.48033003,114.3975336 30.48041545,114.3975517 30.48049169,114.3975592 30.48057846,114.3975636 30.48066131,114.3975696 30.48071787,114.3975862 30.48079417,114.3975877 30.48085473,114.3975877 30.48087181,114.3976378 30.48086523,114.3976393 30.48086664".split(",")));
	}

	@Data
	@AllArgsConstructor
	static class PoolIndex{
		private int index;
		private int notifyCount;
	}
//	@Scheduled(cron = "0/5 * * * * ? ")
	public void scheduledNotify(){

		// 只保留管理员的数据
		List<PatrolTask> patrolTaskList = patrolTaskService.selectList(EPatrolTaskStatus.Proceed);
		patrolTaskList = patrolTaskList.stream().filter(t -> t.getTaskUserId().equals(1L)).collect(Collectors.toList());

		for(int i = 0; i < patrolTaskList.size(); i++){
			PatrolTask patrolTask = patrolTaskList.get(i);
			int index = i % patrolPathPool.size();
			index = index >= patrolPathPool.size() ? 0 : index;
			if(null != poolIndexMap.get(patrolTask.getId())){
				index = poolIndexMap.get(patrolTask.getId()).getIndex();
			}

			poolIndexMap.putIfAbsent(patrolTask.getId(), new PoolIndex(index, 0));
			generatorPath(patrolTask.getId(), patrolTask.getTaskUserName(), index);
		}

	}

	private void generatorPath(Long refId, String userName, int index) {
		Date now = new Date();
		List<String> patrolPathList = patrolPathPool.get(index);

		PoolIndex poolIndex = poolIndexMap.get(refId);
		int notifyCount = poolIndex.getNotifyCount() >= patrolPathList.size() ? 0 : poolIndex.getNotifyCount() + 1;
		poolIndex.setNotifyCount(notifyCount);
		poolIndexMap.put(refId, poolIndex);

		PatrolPathSaveRequest request = new PatrolPathSaveRequest();
		request.setRefId(refId.toString());
		request.setRefType("patrolLog");
		request.setUserName(userName);
		request.setLonLat(patrolPathList.get(notifyCount).replace(" ", ","));
		request.setPatrolDatetime(now);
		notifyPatrolPath(request);

		// 路径放到缓存
		String redisKey = String.format("%s:%s", request.getRefId(), DateUtil
			.format(now, PURE_DATETIME_PATTERN));
		redisService.setCacheObject(EPatrolRedisKey.PatrolPath, redisKey, JSONObject.toJSONString(request));

		// 如果上传了巡查轨迹，那么今天就在线
		if(!redisService.hasKey(EPatrolRedisKey.TodayPatrolTask, String.valueOf(request.getRefId()))){
			long timeout = DateUtil.between(now, DateUtil.endOfDay(now), DateUnit.SECOND);
			redisService.setCacheObject(EPatrolRedisKey.TodayPatrolTask, String.valueOf(request.getRefId()),
				String.valueOf(request.getRefId()), timeout);
		}
	}

	@Override
	public void afterConnectionEstablished(WebSocketSession session) throws Exception {
		log.info("WebSocket连接启动成功");
		webSocketSessionList.add(session);
	}

	@Override
	public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
		log.error("WebSocket错误：" + exception.getMessage());
		webSocketSessionList.remove(session);
	}

	@Override
	public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
		log.debug("WebSocket连接已关闭");
		webSocketSessionList.remove(session);
	}
}
